~ chicken-core (chicken-5) /manual/Cross development
Trap1[[tags: manual]]
2[[toc:]]
3
4
5== Cross Development
6
7Since CHICKEN generates C code, it is relatively easy to create
8programs and libraries for a different architecture than the one the
9compiler is executing on, a process commonly called ''cross
10compiling''. Basically you can simply compile Scheme code to C and
11then invoke your target-specific cross compiler. To automate the
12process of invoking the correct C compiler with the correct settings
13and to simplify the use of extensions, CHICKEN can be built in a
14special "cross-compilation" mode.
15
16Note: in the following text we refer to the "target" as being the
17platform on which the software is intended to run in the end. We use
18the term "host" as the system that builds this software. Others use a
19different nomenclature or switch the meaning of the words.
20
21=== Preparations
22
23Make sure you have a cross-toolchain in your {{PATH}}. In this
24example, a Linux system is used to generate binaries for an ARM based
25embedded system.
26
27==== Building the target libraries
28
29First you need a version of the runtime system ({{libchicken}}),
30compiled for the target system. Obtain and unpack a tarball of the
31CHICKEN sources, or check out the code from the official code
32repository, then build the libraries and necessary development files:
33
34 make ARCH= \
35 PREFIX=/usr \
36 PLATFORM=linux \
37 HOSTSYSTEM=arm-none-linux-gnueabi \
38 DESTDIR=$HOME/target \
39 TARGET_FEATURES="-no-feature x86 -feature arm" \
40 install
41
42This will build CHICKEN and install it in {{~/target}}, which we use
43as a temporary place to store the target files. A few things to note:
44
45* {{ARCH}} is empty, since we don't want the build process to detect the architecture (since the target-architecture is likely to be different). If you know the right string to represent target architecture, you can set {{ARCH}} with that value. This string is passed to the {{-arch}} compiler and linker option for ios and sometimes conditionally checked in platform-specific makefiles)
46* {{PREFIX}} gives the prefix ''on the target system'', under which the
47libraries will finally be installed. In this case it will be {{/usr/lib}}.
48
49* {{PLATFORM}} determines the target platform. It must be one of the officially
50supported platforms CHICKEN runs on. Note that it actually refer to the extension of a dedicated Makefile (`Makefile.linux` in our case).
51
52* {{HOSTSYSTEM}} is an identifier for the target system and will be used as
53the name prefix of the cross C compiler (in this case {{arm-none-linux-gnueabi-gcc}}).
54If your cross compiler does not follow this convention, pass {{C_COMPILER}} and
55{{LIBRARIAN}} to the {{make(1)}} invocation, with the names of the C compiler and
56{{ar(1)}} tool, respectively.
57
58* {{DESTDIR}} holds the directory where the compiled library files will temporarily
59be installed into.
60
61* {{TARGET_FEATURES}} contains extra options to be passed to the target-specific
62Scheme translator; in this case we disable and enable features so that code like
63the following will do the right thing when cross-compiled:
64
65<enscript hightlight=scheme>
66(cond-expand
67 (x86 <do this ...>)
68 ...)
69</enscript>
70
71* If you obtained the sources from a source-code repository and not
72from an official release tarball, you will need a {{chicken}}
73executable to compile the Scheme sources of the runtime system. In
74this case pass yet another variable to the {{make(1)}} invocation:
75{{CHICKEN=<where the "chicken" executable is>}}.
76
77* You can also put all those variables into a file, say {{config.mk}}
78and run {{make CONFIG=config.mk}}.
79
80You should now have these files on {{~/target}}:
81
82 |-- bin
83 | |-- chicken
84 | |-- chicken-bug
85 | |-- chicken-install
86 | |-- chicken-profile
87 | |-- chicken-status
88 | |-- chicken-uninstall
89 | |-- csc
90 | `-- csi
91 |-- include
92 | |-- chicken-config.h
93 | `-- chicken.h
94 |-- lib
95 | |-- chicken
96 | | `-- 9
97 | | :
98 | |
99 | |-- libchicken.a
100 | |-- libchicken.so -> libchicken.so.9
101 | `-- libchicken.so.9
102 `-- share
103 |-- chicken
104 | |-- doc
105 : ; :
106 | |
107 | `-- setup.defaults
108 `-- man
109 `-- man1
110 :
111
112You should now transfer {{~/target/usr/lib}} to the target system, and place
113its contents in {{/usr/lib}}. You may want to omit the static library {{libchicken.a}} if the target memory is limited.
114
115==== Building the "cross chicken"
116
117Next, we will build another chicken, one that uses the cross C compiler to
118generate target-specific code that uses the target-specific runtime library
119we have just built.
120
121Again, unpack a CHICKEN release tarball or a source tree and run
122{{make(1)}} once again:
123
124 make PLATFORM=linux \
125 PREFIX=$HOME/cross-chicken \
126 TARGETSYSTEM=arm-none-linux-gnueabi \
127 PROGRAM_PREFIX=arm- \
128 TARGET_PREFIX=$HOME/target/usr \
129 TARGET_RUN_PREFIX=/usr \
130 install
131
132* {{PREFIX}} gives the place where the "cross chicken" should be installed
133into. It is recommended not to install into a standard location (like {{/usr/local}}
134or {{$HOME}}) - some files will conflict with a normal CHICKEN installation.
135
136* {{TARGETSYSTEM}} gives the name-prefix of the cross C compiler and other tools (C++ compiler, librarian (ar) and ressource compiler (for windows)).
137
138* {{PROGRAM_PREFIX}} determines the name-prefix of the CHICKEN tools to be created.
139
140* {{TARGET_PREFIX}} specifies where the target-specific files (libraries and
141headers) are located. This is the location where we installed the runtime
142system into.
143
144* {{TARGET_RUN_PREFIX}} holds the PREFIX that will be effective at runtime
145(so {{libchicken.so}} will be found in {{$TARGET_RUN_PREFIX/lib}}).
146
147* Make sure to use the same version of the CHICKEN sources for the target and
148the cross build.
149
150* If you build the cross chicken from repository sources, the same note
151about the {{CHICKEN}} variable applies as given above.
152
153In {{~/cross-chicken}}, you should find the following:
154
155 |-- bin
156 | |-- arm-chicken
157 | |-- arm-chicken-install
158 | |-- arm-chicken-profile
159 | |-- arm-chicken-status
160 | |-- arm-chicken-uninstall
161 | |-- arm-csc
162 | `-- arm-csi
163 |-- include
164 | |-- chicken-config.h
165 | `-- chicken.h
166 |-- lib
167 | |-- chicken
168 | | `-- 9
169 | | :
170 | |
171 | |-- libchicken.a
172 | |-- libchicken.so -> libchicken.so.9
173 | `-- libchicken.so.9
174 `-- share
175 |-- chicken
176 | |-- doc
177 : ; :
178 | |
179 | `-- setup.defaults
180 `-- man
181 `-- man1
182 :
183
184To make sure that the right C compiler is used, we ask {{arm-csc}} to show
185the name of the cross C compiler:
186
187 % ~/cross-chicken/bin/arm-csc -cc-name
188 arm-none-linux-gnueabi-gcc
189
190Looks good.
191
192==== Special notes for Linux to Windows cross development
193
194To cross compile from Linux to Windows, you will need to use a Linux build of MingGW-w64 with you can find in most distribution.
195
196As far as the runtime is concerned, the procedure is the same that what have been shown before, using the platform name {{cross-linux-mingw}}.
197
198The procedure to compile the compiler however require some more care:
199* The platform name is {{linux}} because it is where you want your compiler to run.
200* You have to change {{TARGET_LIBRARIES}} to {{-lm -lws2_32}}.
201* You have to make sure you are pointing to the right toolchain (see next paragraph).
202
203In order to compile the C sources that Chicken will produce you have to make sure that you provide the right toolchain in both runtime and compiler steps.
204
205In most cases, you want to do that by setting {{HOSTSYSTEM}} when building the runtime and {{TARGETSYSTEM}} when building the compiler to something similar to {{x86_64-w64-mingw32}} (check you distribution binaries). For example:
206
207 # build a CHICKEN runtime for windows
208 > make PREFIX=$HOME/target PLATFORM=cross-linux-mingw HOSTSYSTEM=x86_64-w64-mingw32 install
209 > make confclean
210 # build a CHICKEN cross-compiler that uses the runtime above
211 > make PREFIX=$HOME/cross PROGRAM_PREFIX=mingw- TARGET_PREFIX=$HOME/target PLATFORM=linux TARGETSYSTEM=x86_64-w64-mingw32 TARGET_LIBRARIES="-lm -lws2_32" install
212
213If your distribution does not stick to the {{PREFIX-TOOLNAME}} convention you may want to set some following variables (runtime step/compiler step):
214* {{C_COMPILER}}/{{TARGET_C_COMPILER}}
215* {{CXX_COMPILER}}/{{TARGET_CXX_COMPILER}}
216* {{LIBRARIAN}}/{{TARGET_LIBRARIAN}} for {{ar}}
217* {{RC_COMPILER}}/{{TARGET_RC_COMPILER}} for {{windres}}
218
219You may need this trick to pick {{x86_64-w64-mingw32-gcc-posix}} over {{x86_64-w64-mingw32-gcc-win32}} in Debian for example (those correspond to different thread APIs).
220
221=== Using it
222
223==== Compiling simple programs
224
225 % ~/cross-chicken/bin/arm-csc -v hello.scm
226 /home/felix/cross-chicken/arm-cross-chicken/bin/arm-chicken hello.scm -output-file hello.c -quiet
227 arm-none-linux-gnueabi-gcc hello.c -o hello.o -c -fno-strict-aliasing -DHAVE_CHICKEN_CONFIG_H -g -Wall \
228 -Wno-unused -I /home/felix/cross-chicken/arm-chicken/include
229 rm hello.c
230 arm-none-linux-gnueabi-gcc hello.o -o hello -L/home/felix/cross-chicken/arm-chicken/lib -Wl,-R/usr/lib -lm \
231 -ldl -lchicken
232 rm hello.o
233
234Is it an ARM binary?
235
236 % file hello
237 hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.16, dynamically linked (uses shared libs), not stripped
238
239Yes, looks good.
240
241==== Compiling extensions
242
243By default, the tools that CHICKEN provides to install, list and uninstall
244extensions will operate on both the host and the target repository.
245So running {{arm-chicken-install}} will compile and install the extension
246for the host system and for the cross-target. To selectively install, uninstall
247or list extensions for either the host or the target system use the
248{{-host}} and {{-target}} options for the tools.
249
250For example, using the mingw-cross-compiler from above, we can create
251a standalone Windows exe file that includes the CHICKEN runtime and all
252egg dependencies.
253
254 # install an egg using the mingw cross compiler above
255 > $HOME/cross/bin/mingw-chicken-install fmt
256 > cat hello.scm
257 (import fmt chicken.platform)
258 (fmt #t "hello world from " (software-type) nl
259 (pretty (features)))
260 # create a standalone exe file with the CHICKEN and fmt statically linked
261 > $HOME/cross/bin/mingw-csc -static hello.scm
262 # hello.exe should now run on Window without any runtime DLL dependencies:
263 > x86_64-w64-mingw32-objdump -p hello.exe | grep "DLL Name"
264 DLL Name: KERNEL32.dll
265 DLL Name: msvcrt.dll
266 DLL Name: USER32.dll
267 DLL Name: WS2_32.dll
268 # or using wine
269 > wine hello.exe
270 hello world from windows
271 (#:windows #:64bit #:cross-chicken
272 #:ptables #:dload #:little-endian
273 #:x86-64 #:gnu #:mingw32
274 ...)
275
276
277=== "Target-only" extensions
278
279Sometimes an extension will only be compilable for the target platform
280(for example libraries that use system-dependent features). In this
281case you will have to work around the problem that the host-compiler
282still may need compile-time information from the target-only
283extension, like the import library of modules. One option is to copy
284the import-library source file into the repository of the host compiler:
285
286 # optionally, you can compile the import library:
287 # ~/cross-chicken/bin/arm-csc -O3 -d0 -s target-only-extension.import.scm
288 cp target-only-extension.import.scm ~/cross-chicken/lib/chicken/9
289
290=== Final notes
291
292Cross-development is a very tricky process - it often involves countless
293manual steps and it is very easy to forget an important detail or mix
294up target and host systems. Also, full 100% platform neutrality is
295hard to achieve. CHICKEN tries very hard to make this transparent, but
296at the price of considerable complexity in the code that manages
297extensions.
298
299
300----
301Previous: [[Deployment]]
302
303Next: [[Bugs and limitations]]